/*
 * MathFunction.cpp
 *
 *  Created on: 25 мая 2022 г.
 *      Author: nikitas
 */

#include "MathFunction.h"

namespace STC_calc {

MathFunction::MathFunction(const std::string &str)
{
	std::pair<std::string, string_vector> largs;
	largs = initialize(str);

	func_name = largs.first;
	check_func(func_name);

	if ((func_name == "set")&&(!SemanticAnalyzer::can_convert(largs.second.front())))
		throw (RuntimeErrorClass("Invalid argument: " + largs.second.front()));

	std::vector<std::shared_ptr<FArgument>> ret(largs.second.size());
	int n = 0;

	for (std::string arg : largs.second)
	{
		auto ptr = std::make_shared<FArgument>(arg);
		ret[n] = ptr;
		n++;
	}
	args.resize(ret.size());
	int i = 0;
	for(auto r : ret)
	{
		args[i] = r;
		i++;
	}
}

MathFunction::MathFunction(const MathFunction& that)
{
    this->func_name = that.func_name;

    std::vector<std::shared_ptr<FArgument>> args;
    this->args.resize(that.args.size());

    int i = 0;
    for (auto arg : that.args)
    {
        this->args[i] = arg;
        i++;
    }
}

MathFunction::~MathFunction()
{

}

bool MathFunction::operator ==(const MathFunction& that)
{
    if (this->func_name != that.func_name) return false;
    if (this->args.size() != that.args.size()) return false;
    for (int i = 0; i < that.args.size(); i++)
    {
        if (*this->args[i] != *that.args[i])
    }
}
bool MathFunction::operator !=(const MathFunction& that)
{

}

long double MathFunction::operator()()
{
	return calculate();
}
long double MathFunction::calculate()
{
	auto func = Counter::function_catalog.at(func_name);
	ldouble_vector count_args(args.size());
	int i = 0;
	for (auto arg : args)
	{
		count_args[i] = (*arg)();
		i++;
	}
	return func(count_args);
}

void MathFunction::check_func(const std::string& name)
{
	if (Counter::function_catalog.find(name) != Counter::function_catalog.end()) return;

	std::string str = "Error: Incorrect name ";
	throw(RuntimeErrorClass(str, Enums::fatal));
}

std::pair<std::string, string_vector> MathFunction::initialize(const std::string str)
{
	std::string ret_a;
	string_vector ret_b;
	std::string new_str = str;

	FunctionAnalyzer::remove_brackets(new_str);
	ret_a = FunctionAnalyzer::define_name_function(str);
	ret_b = FunctionAnalyzer::define_func_args(new_str, ret_a);

	return std::pair<std::string, string_vector>(ret_a, ret_b);
}

} /* namespace STC_calc */
